package com.eugenema.windowGui.component;

import com.eugenema.entity.UpdateInfo;
import com.eugenema.service.UpdateService;
import com.eugenema.util.FileUtil;

import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 升级弹窗
 *
 * @author Eugenema
 * @date 2023/5/7 21:19
 **/
public class PopupJFrame extends JFrame {
    /** 点击的按钮 */
    public static Boolean isOk = null;
    /** 文本区域 */
    private JTextPane textPane;
    /** 文本内容 */
    StyledDocument doc;
    /** 文本样式 */
    Style style;
    /** 确定按钮 */
    JButton okButton;
    /** 取消按钮 */
    JButton cancelButton;

    /**
     * 创建升级弹窗
     *
     * @param updateInfo 更新信息
     * @param nowVersionInfo 当前版本信息
     *
     * @author 马寅广
     * @date 2023/10/25 8:59
     **/
    public PopupJFrame(UpdateInfo updateInfo, UpdateInfo nowVersionInfo) {
        super("检测到新版本");

        // 创建文本区域
        textPane = new JTextPane();
        textPane.setEditable(false);
        doc = textPane.getStyledDocument();
        // 设置字体大小为20
        style = textPane.addStyle("FirstLine", null);
        StyleConstants.setFontSize(style, 20);
        StyleConstants.setFontFamily(style, "Monospaced");
        try {
            doc.insertString(doc.getLength(), updateInfo.getContent() + "\n\n\n", style);
        } catch (BadLocationException e) {
            e.printStackTrace();
        }

        // 创建确定和取消按钮
        okButton = new JButton("确定");
        cancelButton = new JButton("取消");

        // 单独更新升级程序
        saveListener(updateInfo, nowVersionInfo);

        // 创建滚动面板，用于显示文本区域
        JScrollPane scrollPane = new JScrollPane(textPane);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        // 为取消按钮添加事件监听器
        cancelButton.addActionListener(e -> {
            isOk = false;
            dispose();
        });

        // 设置右上角关闭按钮事件
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                isOk = false;
                dispose();
            }
        });

        // 创建按钮面板
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(okButton);
        buttonPanel.add(cancelButton);

        // 将滚动面板和按钮面板添加到弹窗中
        getContentPane().add(scrollPane);
        getContentPane().add(buttonPanel, "South");

        // 设置弹窗大小并居中显示
        setSize(400, 300);
        setLocationRelativeTo(null);
        setAlwaysOnTop(true);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    }

    /**
     * 展示弹窗
     *
     * @author Eugenema
     * @date 2023/12/6 22:43
     *
     **/
    public void showJFrame() {
        setVisible(true);
    }

    /**
     * 确定按钮方法：调用升级程序
     *
     * @author Eugenema
     * @date 2023/12/6 22:44
     *
     *
     **/
    public void setOkEvent() {
        isOk = true;
        UpdateService.update();
        // 关闭弹窗
        dispose();
    }

    /**
     * 确定按钮增加监听
     * </br> 若需更新升级程序，确定按钮实现升级程序下载
     * </br> 否则，确定按钮会直接启动升级程序
     *
     * @author Eugenema
     * @date 2023/12/6 22:17
     *
     * @param updateInfo 更新信息
     * @param nowVersionInfo 当前版本信息
     *
     **/
    private void saveListener(UpdateInfo updateInfo, UpdateInfo nowVersionInfo) {
        // 校验是否需要更新升级程序
        List<UpdateInfo> upgradeInfoList = updateInfo.getUpdateList().stream().filter(updateInfoNode -> updateInfoNode.getRelativePath().endsWith(UpdateService.UPDATE_FILE)).collect(Collectors.toList());
        if (!upgradeInfoList.isEmpty()) {
            // 更新升级程序
            // 1、设置更新内容
            /** 文本区域第二行插入位置 */
            int length = doc.getLength();
            // 设置第二行的字体大小为15
            style = textPane.addStyle("SecondLine", null);
            StyleConstants.setFontSize(style, 15);
            StyleConstants.setFontFamily(style, "Monospaced");
            try {
                doc.insertString(length, "本次需要更新升级程序\n点击’确定‘开始下载！", style);
            } catch (BadLocationException e) {
                e.printStackTrace();
            }

            // 2、添加确定按钮事件监听
            okButton.addActionListener(e -> {
                // 禁用确定按钮、取消按钮
                okButton.setVisible(false);
                cancelButton.setVisible(false);

                // 进度条
                JProgressBar progressBar = new JProgressBar();
                progressBar.setStringPainted(true);
                add(progressBar, "South");
                setVisible(true);

                ExecutorService executor = Executors.newSingleThreadExecutor();
                executor.execute(() -> {
                    // 执行长时间运行的任务
                    try {
                        setTitle("正在更新升级程序");
                        // 更新升级程序
                        downloadUpdateFile(FileUtil.BASE_PATH + upgradeInfoList.get(0).getRelativePath(), upgradeInfoList.get(0).getUrl(), progressBar);

                        // 设置更新时间并更新标志文件
                        nowVersionInfo.setUpdateTime(new Date());
                        nowVersionInfo.setVersionUpdate(updateInfo.getVersionUpdate());
                        FileUtil.write(UpdateService.UPDATE_FLAG_FILE, nowVersionInfo.toString());

                        // 调用升级程序
                        setOkEvent();
                    } catch (Exception e1) {
                        // 弹出异常对话框
                        JOptionPane.showMessageDialog(null, "升级失败！\n请稍候重试，或联系开发人员");
                        e1.printStackTrace();
                        System.exit(0);
                    }
                });
                executor.shutdown();
            });
        } else {
            // 为确定按钮添加事件监听器
            okButton.addActionListener(e -> {
                setOkEvent();
            });
        }
    }

    /**
     * 下载文件并更新
     *
     * @author Eugenema
     * @date 2023/12/7 22:39
     *
     * @param filePath 文件全路径
     * @param urlString url
     * @param progressBar 进度条
     *
     **/
    private void downloadUpdateFile(String filePath, String urlString, JProgressBar progressBar) {
        // 删除原文件
        File file = new File(filePath);
        file.delete();

        // 创建文件路径
        file.getParentFile().mkdirs();

        // 更新文件
        if (urlString != null && !urlString.trim().isEmpty()) {
            try {
                // 下载新文件
                URL url = new URL(urlString);
                URLConnection conn = url.openConnection();
                InputStream inputStream = conn.getInputStream();
                FileOutputStream outputStream = new FileOutputStream(file);
                byte[] buffer = new byte[1024];
                int len;
                int totalBytesRead = 0;
                int fileSize = conn.getContentLength();
                while ((len = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                    totalBytesRead += len;
                    int progress = (int) ((double) totalBytesRead / (double) fileSize * 100);
                    progressBar.setValue(progress);
                }
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}